﻿using Azure.Core;
using Microsoft.AspNetCore.Http;
using StackExchange.Redis;
using System.Text.Json;

public class WeChatAuthService : IWeChatAuthService
{
    private readonly IHttpClientFactory _httpClientFactory;
    private readonly IConfiguration _configuration;
    private readonly IRedisService _redisService;
    private readonly ISessionManager _sessionManager;
    private readonly IHttpContextAccessor _httpContextAccessor;
    private readonly ILogger<WeChatAuthService> _logger;

    private const string WECHAT_AUTH_URL = "https://open.weixin.qq.com/connect/oauth2/authorize";
    private const string WECHAT_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";
    private const string WECHAT_USERINFO_URL = "https://api.weixin.qq.com/sns/userinfo";
    private readonly TimeSpan _stateExpiry = TimeSpan.FromMinutes(10);

    public WeChatAuthService(
        IHttpClientFactory httpClientFactory,
        IConfiguration configuration,
        IRedisService redisService,
        ISessionManager sessionManager,
        IHttpContextAccessor httpContextAccessor,
        ILogger<WeChatAuthService> logger)
    {
        _httpClientFactory = httpClientFactory;
        _configuration = configuration;
        _redisService = redisService;
        _sessionManager = sessionManager;
        _httpContextAccessor = httpContextAccessor;
        _logger = logger;
    }




    /// <summary>
    /// redirectUri:微信确认后，返回的地址：auth-callback.html
    /// returnUrl：业务需求发起的地址【最终返回此地址】
    /// </summary>
    /// <param name="redirectUri"></param>
    /// <param name="returnUrl"></param>
    /// <param name="silentAuth"></param>
    /// <returns></returns>
    public async Task<string> GenerateAuthUrlAsync(string returnUrl, bool silentAuth = false)
    {
        var appId = _configuration["WeChat:AppId"];
        var scope = silentAuth ? "snsapi_base" : "snsapi_userinfo";
        var state = GenerateStateToken();
         

        var redirectUri = $"{_httpContextAccessor.HttpContext?.Request.Scheme}://{_httpContextAccessor.HttpContext?.Request.Host}/auth-callback.html";
        redirectUri = redirectUri + "?pageid=" + returnUrl;

        // 存储state到Redis - 使用强类型StateInfo
        var stateKey = GetStateKey(state);

        var stateInfo = new StateInfo
        {
            RedirectUri = redirectUri,
            ReturnUrl   = returnUrl,
            OriginalHost = _httpContextAccessor.HttpContext?.Request.Host.ToString(),
            OriginalScheme = _httpContextAccessor.HttpContext?.Request.Scheme,
            UserAgent = _httpContextAccessor.HttpContext?.Request.Headers["User-Agent"].ToString(),
            CreatedAt = DateTime.UtcNow,
            IsSilentAuth = silentAuth
        };

        await _redisService.SetAsync(stateKey, stateInfo, _stateExpiry);

        _logger.LogInformation("生成微信授权URL - Scope: {Scope}, redirectUri: {redirectUri}", scope, redirectUri);

        return $"{WECHAT_AUTH_URL}?appid={appId}&redirect_uri={Uri.EscapeDataString(redirectUri)}&response_type=code&scope={scope}&state={state}#wechat_redirect";
    }

    public async Task<AuthProcessResult> ProcessAuthorizationAsync(string code, string state)
    {
        // 验证state
        if (!await ValidateStateAsync(state))
        {
            throw new ArgumentException("无效的state参数或已过期");
        }

        // 获取state信息 - 使用强类型StateInfo
        var stateKey = GetStateKey(state);
        var stateInfo = await _redisService.GetAsync<StateInfo>(stateKey);

        if (stateInfo == null)
        {
            throw new ArgumentException("无效的state参数");
        }

        //删除已使用的state
        await RemoveStateAsync(state);

        string returnUrl = stateInfo.ReturnUrl ?? $"{_httpContextAccessor.HttpContext?.Request.Scheme}://{_httpContextAccessor.HttpContext?.Request.Host}";

        _logger.LogInformation("处理微信授权回调 - Code: {Code}, ReturnUrl: {ReturnUrl}", code, returnUrl);

        // 获取access_token
        var tokenResult = await ExchangeCodeForToken(code);
        if (!tokenResult.IsSuccess)
        {
            _logger.LogWarning("微信Token获取失败: {Error}", tokenResult.ErrorMessage);
            throw new Exception($"微信授权失败: {tokenResult.ErrorMessage}");
        }

        // 获取用户信息
        WeChatUserInfo userInfo;
        if (tokenResult.Scope == "snsapi_userinfo")
        {
            userInfo = await GetUserInfoAsync(tokenResult.AccessToken, tokenResult.OpenId);
        }
        else
        {
            userInfo = new WeChatUserInfo
            {
                OpenId = tokenResult.OpenId,
                Scope = tokenResult.Scope,
                NickName = "微信用户"
            };
        }

        // 创建会话
        var session = await _sessionManager.CreateSessionAsync(userInfo, tokenResult);

        return new AuthProcessResult
        {
            Success = true,
            Session = session,
            ReturnUrl = returnUrl,
            UserInfo = userInfo
        };
    }

    public async Task<bool> ValidateStateAsync(string state)
    {
        if (string.IsNullOrEmpty(state))
            return false;

        var stateKey = GetStateKey(state);
        return await _redisService.ExistsAsync(stateKey);
    }

    public async Task RemoveStateAsync(string state)
    {
        var stateKey = GetStateKey(state);
        await _redisService.RemoveAsync(stateKey);
    }

    public async Task<WeChatUserInfo> GetUserInfoAsync(string accessToken, string openId)
    {
        var client = _httpClientFactory.CreateClient();
        var url = $"{WECHAT_USERINFO_URL}?access_token={accessToken}&openid={openId}&lang=zh_CN";

        var response = await client.GetAsync(url);
        var content = await response.Content.ReadAsStringAsync();

        if (!response.IsSuccessStatusCode)
        {
            throw new Exception($"获取用户信息失败: {response.StatusCode}");
        }

        var userInfo = JsonSerializer.Deserialize<WeChatUserInfo>(content);

        if (userInfo?.OpenId == null)
        {
            throw new Exception("获取用户信息失败");
        }

        return userInfo;
    }

    private async Task<WeChatTokenResponse> ExchangeCodeForToken(string code)
    {
        var client = _httpClientFactory.CreateClient();
        var appId = _configuration["WeChat:AppId"];
        var appSecret = _configuration["WeChat:AppSecret"];

        var url = $"{WECHAT_TOKEN_URL}?appid={appId}&secret={appSecret}&code={code}&grant_type=authorization_code";

        var response = await client.GetAsync(url);
        var content = await response.Content.ReadAsStringAsync();

        if (!response.IsSuccessStatusCode)
        {
            throw new Exception($"微信API请求失败: {response.StatusCode}");
        }

        var result = JsonSerializer.Deserialize<WeChatTokenResponse>(content);

        if (result == null || !string.IsNullOrEmpty(result.ErrorCode))
        {
            throw new Exception($"微信授权失败: {result?.ErrorMessage}");
        }

        return result;
    }

    private string GenerateStateToken()
    {
        return Guid.NewGuid().ToString("N") + DateTime.UtcNow.Ticks.ToString("x");
    }

    private string GetStateKey(string state) => $"auth_state:{state}";
}